
#include "Mode_UTest.h"
#include "Mode.h"
#include "basic_api.h"
/********* interior	define ***********/

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#define LLOG_TICK
#include "llog.h"

#ifdef	CFG_STATIC_BUF_ALLOCATE
#define L_MALLOC 	SMalloc
#define L_FREE(A) 	LLOG_ERR()
#else
#define L_MALLOC 	malloc
#define L_FREE(A)	free(A)
#endif
/********** global val ***************/

/******* local function **************/

/******* TODO ************************/


//==== 基于 BFIFO 的一个 vPort 为了协议测试 
//==== 基于 PkgQueue 的一个vPort 为了协议测试;
//==== 基于 MsgQueue 的一个vPort 为了协议测试;



//=============

#ifdef CFG_UT_VPPMGM

#define UT_OC_PTCL_ECHO

/* static int Ptcl_Ctrl_Demo(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	int ret =RET_ERR;
	
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I PTCL Cmd: STOP		\n");}break;
		case GCMD_START		:{ LLOG("#I PTCL Cmd: START		\n");}break;
		case GCMD_CLEAN		:{ LLOG("#I PTCL Cmd: CLEAN		\n");}break;
		case GCMD_RESET		:{ LLOG("#I PTCL Cmd: RESET		\n");}break;
		case GCMD_GET_STATE	:{ LLOG("#I PTCL Cmd: GET_STATE	\n");}break;
	}
	ret = RET_OK;
	return ret;
} */

// Ptcl : EchoPtcl : 数据回环;满16byte回发
int (*g_PtclWrite[3])(uint16_t ,uint8_t* );
uint8_t g_PtclRxCnt[3];

static int Ptcl_A_RecoAndParser(uint8_t ch){
	// 定长数据包
	static uint8_t FixPkg[16];
	uint8_t index = 0;
	
	FixPkg[g_PtclRxCnt[index]++] = ch;
	if(g_PtclRxCnt[index] == sizeof(FixPkg)){
		g_PtclRxCnt[index] = 0;
		#ifdef UT_OC_PTCL_ECHO
		Log_ShowArray("Ptcl A Pkg",sizeof(FixPkg),&FixPkg[0]);
		#endif
		if(g_PtclWrite[index] != NULL){
			g_PtclWrite[index](sizeof(FixPkg),&FixPkg[0]);
		}
	}
	return RET_OK;
}

static int Ptcl_A_BindWrite(int (*pFunc)(uint16_t ,uint8_t* )){
	LLOG("#I Ptcl A BindWrite:[0x%x]\n",pFunc);
	g_PtclWrite[0]=pFunc;
	return RET_OK;
}

static int Ptcl_A_Ctrl_Demo(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	int ret =RET_ERR;
	
	uint8_t index = 0;
	
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I PTCL A Cmd: STOP		\n");}break;
		case GCMD_START		:{ LLOG("#I PTCL A Cmd: START		\n");}break;
		case GCMD_CLEAN		:{ LLOG("#I PTCL A Cmd: CLEAN		\n"); g_PtclRxCnt[index]=0; }break;
		case GCMD_RESET		:{ LLOG("#I PTCL A Cmd: RESET		\n");}break;
		case GCMD_GET_STATE	:{ LLOG("#I PTCL A Cmd: GET_STATE	\n");}break;
	}
	ret = RET_OK;
	return ret;
}

static int Ptcl_B_RecoAndParser(uint8_t ch){
	// 定长数据包
	static uint8_t FixPkg[16];
	uint8_t index = 1;
	
	FixPkg[g_PtclRxCnt[index]++] = ch;
	if(g_PtclRxCnt[index] == sizeof(FixPkg)){
		g_PtclRxCnt[index] = 0;
		#ifdef UT_OC_PTCL_ECHO
		Log_ShowArray("Ptcl B Pkg",sizeof(FixPkg),&FixPkg[0]);
		#endif
		if(g_PtclWrite[index] != NULL){
			g_PtclWrite[index](sizeof(FixPkg),&FixPkg[0]);
		}
	}
	return RET_OK;
}

static int Ptcl_B_BindWrite(int (*pFunc)(uint16_t ,uint8_t* )){
	LLOG("#I Ptcl B BindWrite:[0x%x]\n",pFunc);
	g_PtclWrite[1]=pFunc;
	return RET_OK;
}

static int Ptcl_B_Ctrl_Demo(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	int ret =RET_ERR;
	
	uint8_t index = 1;
	
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I PTCL B Cmd: STOP		\n");}break;
		case GCMD_START		:{ LLOG("#I PTCL B Cmd: START		\n");}break;
		case GCMD_CLEAN		:{ LLOG("#I PTCL B Cmd: CLEAN		\n"); g_PtclRxCnt[index]=0; }break;
		case GCMD_RESET		:{ LLOG("#I PTCL B Cmd: RESET		\n");}break;
		case GCMD_GET_STATE	:{ LLOG("#I PTCL B Cmd: GET_STATE	\n");}break;
	}
	ret = RET_OK;
	return ret;
}

static int Ptcl_C_RecoAndParser(uint8_t ch){
	// 定长数据包
	static uint8_t FixPkg[16];
	uint8_t index = 2;
	
	FixPkg[g_PtclRxCnt[index]++] = ch;
	if(g_PtclRxCnt[index] == sizeof(FixPkg)){
		g_PtclRxCnt[index] = 0;
		#ifdef UT_OC_PTCL_ECHO
		Log_ShowArray("Ptcl C Pkg",sizeof(FixPkg),&FixPkg[0]);
		#endif
		if(g_PtclWrite[index] != NULL){
			g_PtclWrite[index](sizeof(FixPkg),&FixPkg[0]);
		}
	}
	return RET_OK;
}

static int Ptcl_C_BindWrite(int (*pFunc)(uint16_t ,uint8_t* )){
	LLOG("#I Ptcl C BindWrite:[0x%x]\n",pFunc);
	g_PtclWrite[2]=pFunc;
	return RET_OK;
}

static int Ptcl_C_Ctrl_Demo(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	int ret =RET_ERR;
	
	uint8_t index = 2;
	
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I PTCL C Cmd: STOP		\n");}break;
		case GCMD_START		:{ LLOG("#I PTCL C Cmd: START		\n");}break;
		case GCMD_CLEAN		:{ LLOG("#I PTCL C Cmd: CLEAN		\n"); g_PtclRxCnt[index]=0; }break;
		case GCMD_RESET		:{ LLOG("#I PTCL C Cmd: RESET		\n");}break;
		case GCMD_GET_STATE	:{ LLOG("#I PTCL C Cmd: GET_STATE	\n");}break;
	}
	ret = RET_OK;
	return ret;
}

// Port
static int Port_Ctrl_Demo(uint16_t Cmd,uint16_t Len,uint8_t* pPara){
	int ret =RET_ERR;
	
	Len=Len;
	pPara = pPara;
	switch(Cmd){
		case GCMD_STOP		:{ LLOG("#I Port Cmd: STOP		\n");}break;
		case GCMD_START		:{ LLOG("#I Port Cmd: START		\n");}break;
		case GCMD_CLEAN		:{ LLOG("#I Port Cmd: CLEAN		\n");}break;
		case GCMD_RESET		:{ LLOG("#I Port Cmd: RESET		\n");}break;
		case GCMD_GET_STATE	:{ LLOG("#I Port Cmd: GET_STATE	\n");}break;
	}
	ret = RET_OK;
	return ret;
}

static uint8_t g_PortAStr[]="PortA_1234567890";
static uint8_t g_PortBStr[]="PortB_0123456789";
static uint8_t g_PortCStr[]="PortC_0987654321";

static uint8_t g_PortAOutBuf[20];
static uint8_t g_PortBOutBuf[20];
static uint8_t g_PortCOutBuf[20];

static int Port_A_Write(uint16_t Len,uint8_t* pPkg){
	Log_ShowArray("Port A Out",Len,pPkg);
	MEMCPY(&g_PortAOutBuf[0],pPkg,Len);	
	return RET_OK;
}

static int Port_A_Read(uint16_t RLen,uint8_t* pRBuf){
	
	int copyNum = 0;

	copyNum = sizeof(g_PortAStr)-1;
	copyNum = (RLen > copyNum)?copyNum:RLen;
	
	MEMCPY(pRBuf,&g_PortAStr[0],copyNum);	
	return copyNum;
}

static int Port_B_Write(uint16_t Len,uint8_t* pPkg){
	Log_ShowArray("Port B Out",Len,pPkg);
	MEMCPY(&g_PortBOutBuf[0],pPkg,Len);
	return RET_OK;
}

static int Port_B_Read(uint16_t RLen,uint8_t* pRBuf){
	
	int copyNum = 0;

	copyNum = sizeof(g_PortBStr)-1;
	copyNum = (RLen > copyNum)?copyNum:RLen;
	
	MEMCPY(pRBuf,&g_PortBStr[0],copyNum);	
	return copyNum;
}

static int Port_C_Write(uint16_t Len,uint8_t* pPkg){
	Log_ShowArray("Port C Out",Len,pPkg);
	MEMCPY(&g_PortCOutBuf[0],pPkg,Len);
	return RET_OK;
}

static int Port_C_Read(uint16_t RLen,uint8_t* pRBuf){
	
	int copyNum = 0;

	copyNum = sizeof(g_PortCStr)-1;
	copyNum = (RLen > copyNum)?copyNum:RLen;
	
	MEMCPY(pRBuf,&g_PortCStr[0],copyNum);	
	return copyNum;
}

//
static const tvPortAPISet g_PortRegAPI[] = {
	{
		.pWrite = Port_A_Write,
		.pRead 	= Port_A_Read,
		.pCtrl	= Port_Ctrl_Demo,
	},
	{
		.pWrite = Port_B_Write,
		.pRead 	= Port_B_Read,
		.pCtrl	= Port_Ctrl_Demo,
	},
	{
		.pWrite = Port_C_Write,
		.pRead 	= Port_C_Read,
		.pCtrl	= Port_Ctrl_Demo,
	},
};

static const tvPtclAPISet g_PtclRegAPI[] = {
	
	{
		.pRecoAndParser = Ptcl_A_RecoAndParser,
		.pBindWrite 	= Ptcl_A_BindWrite,
		.pCtrl			= Ptcl_A_Ctrl_Demo,
	},
	{
		.pRecoAndParser = Ptcl_B_RecoAndParser,
		.pBindWrite 	= Ptcl_B_BindWrite,
		.pCtrl			= Ptcl_B_Ctrl_Demo,
	},
	{
		.pRecoAndParser = Ptcl_C_RecoAndParser,
		.pBindWrite 	= Ptcl_C_BindWrite,
		.pCtrl			= Ptcl_C_Ctrl_Demo,
	},	
};


//
static tvPPMgm* g_pPPMgm;

static int CoTask_vPpMgm_TestGuard(void* pPara){
	static uint8_t Flag=0;
	//
	if(Flag == 0){
		Flag=1;
		vPPMgm_SwitchConnect(g_pPPMgm,1,1); 
		vPPMgm_SwitchConnect(g_pPPMgm,2,2);	
		vPPMgm_SwitchConnect(g_pPPMgm,3,3);	
	}
	else{
		Flag=0;
		//
		vPPMgm_SwitchConnect(g_pPPMgm,1,2);	
		vPPMgm_SwitchConnect(g_pPPMgm,2,3);	
		vPPMgm_SwitchConnect(g_pPPMgm,3,1);	
	}
}

static int UT_vPPMgm(void){
	
	int ret=RET_ERR;
	int i;
	
	tvPtcl* PtclObj[6];
	tvPort* PortObj[6];
	tvPPMgm* pObj;
	
	LLOG_MARK();
	pObj = vPPMgm_Create(7);
	g_pPPMgm = pObj;
	
	i=1;
	PtclObj[i++] = vPPMgm_CreatePtclAndAdd(pObj,i,&g_PtclRegAPI[i-1]);
	PtclObj[i++] = vPPMgm_CreatePtclAndAdd(pObj,i,&g_PtclRegAPI[i-1]);
	PtclObj[i++] = vPPMgm_CreatePtclAndAdd(pObj,i,&g_PtclRegAPI[i-1]);
	

	
	i=1;
	PortObj[i++] = vPPMgm_CreatePortAndAdd(pObj,i,&g_PortRegAPI[i-1],500,40);
	PortObj[i++] = vPPMgm_CreatePortAndAdd(pObj,i,&g_PortRegAPI[i-1],500,40);
	PortObj[i++] = vPPMgm_CreatePortAndAdd(pObj,i,&g_PortRegAPI[i-1],500,40);

	#if 0
	i=1;
	vPtcl_Show(PtclObj[i++]);
	vPtcl_Show(PtclObj[i++]);
	vPtcl_Show(PtclObj[i++]);	
	
	i=1;
	vPort_Show(PortObj[i++]);
	vPort_Show(PortObj[i++]);
	vPort_Show(PortObj[i++]);
	#endif
	
	
	//
	LLOG("\n");vPPMgm_SwitchConnect(pObj,1,1); // vPtcl_Show(PtclObj[1]);vPort_Show(PortObj[1]);
	LLOG("\n");vPPMgm_SwitchConnect(pObj,2,2); // vPtcl_Show(PtclObj[2]);vPort_Show(PortObj[2]);
	LLOG("\n");vPPMgm_SwitchConnect(pObj,3,3); // vPtcl_Show(PtclObj[3]);vPort_Show(PortObj[3]);

	//
	LLOG("\n");vPPMgm_SwitchConnect(g_pPPMgm,1,2);	// vPtcl_Show(PtclObj[1]);vPort_Show(PortObj[2]);
	LLOG("\n");vPPMgm_SwitchConnect(g_pPPMgm,2,3);	// vPtcl_Show(PtclObj[2]);vPort_Show(PortObj[3]);
	LLOG("\n");vPPMgm_SwitchConnect(g_pPPMgm,3,1);	// vPtcl_Show(PtclObj[3]);vPort_Show(PortObj[1]);
	#ifdef 	CFG_SORT_TIMER
	do{
		tSTimer* pTimer;
		pTimer = STimer_CreateAndAdd(0, STIMER_TYP_PERIOD, 1200);
		STimer_BindCBF(pTimer,CoTask_vPpMgm_TestGuard);
		STimer_OnOff(pTimer,1);	

	}while(0);
	#endif
	
	// note 不支持俩组端口交叉
	
	return ret;
}

#endif

void Mode_UTest(void){

	#ifdef CFG_UT_VPPMGM
	UT_vPPMgm();
	#endif

}








